package com.example.lambda.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Set;

/**
 * @Auther: わらい
 * @Time: 2021/8/25 10:00
 */
@Slf4j
public class ApiSignUtil {


    /**
     *  校验加密参数
     * @param data 所有的body参数都在这里
     * @param secret 加密用的secret
     * @param signField 已生成的密文名称
     * @return 校验是否通过
     */
    public static boolean check(Object data, String secret, String signField) {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(data));
        if (!jsonObject.containsKey(signField)) {
            return false;
        }
        String sign = jsonObject.getString(signField);
        jsonObject.remove(signField);
        return sign(jsonObject, secret).equals(sign);
    }

    /**
     *  生成密文
     * @param data 所有的body参数都在这里
     * @param secret 加密用的secret
     * @return 密文
     */
    public static String sign(Object data, String secret) {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(data, SerializerFeature.MapSortField), Feature.OrderedField);
        Set<String> keySet = jsonObject.keySet();
        String[] keyArray = keySet.toArray(new String[0]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (jsonObject.getString(k).trim().length() > 0) {
                sb.append(k).append("=").append(jsonObject.getString(k).trim()).append("&");
            }
        }

        sb.append("key=").append(secret);
        log.info("验签参数：{}", sb.toString());
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
            StringBuilder md5code = new StringBuilder(new BigInteger(1, array).toString(16));
            for (int i = 0; i < 32 - md5code.length(); i++) {
                md5code.insert(0, "0");
            }
            return md5code.toString();
        } catch (Exception e) {
            throw new RuntimeException("生成md5加密字符串时出错", e);
        }
    }
}
